//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _APPS_BUSH_PARSER_CPYTHONFLOAT_H_
#define _APPS_BUSH_PARSER_CPYTHONFLOAT_H_

#include <buola/buola.h>

namespace buola { namespace bush { namespace token {

struct CPythonFloat
{
    typedef std::wstring::const_iterator tIt;
    
    static bool ParseExpPart(tIt &pB,const tIt &pE)
    {
        bool lOK=false;
        bool lSign=false;
        
        for(++pB;pB!=pE;++pB)
        {
            switch(*pB)
            {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                lOK=true;
                break;
            case 'j':
            case 'J':
                if(lOK)
                {
                    pB++;
                    return true;
                }
                else
                    return false;
            case '-':
            case '+':
                if(lOK||lSign) return false;
                lSign=true;
                break;
            default:
                return lOK;
            }
        }
        return lOK;
    }

    static bool ParsePointPart(tIt &pB,const tIt &pE,bool pEmptyOK)
    {
        bool lOK=pEmptyOK;
        
        for(++pB;pB!=pE;++pB)
        {
            switch(*pB)
            {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                lOK=true;
                break;
            case ',':
                return lOK;
            case 'e':
            case 'E':
                if(!lOK)
                    return false;
                else
                {
                    tIt lI=pB;
                    if(!ParseExpPart(pB,pE))
                    {
                        pB=lI;
                    }
                    return true;
                }
            case 'j':
            case 'J':
                if(lOK)
                {
                    pB++;
                    return true;
                }
                else
                    return false;
            default:
                return lOK;
            }
        }
        
        return lOK;
    }
    
    static bool ParseIntPart(tIt &pB,const tIt &pE)
    {
        for(;pB!=pE;++pB)
        {
            switch(*pB)
            {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                break;
            case '.':
                return ParsePointPart(pB,pE,true);
            case 'E':
            case 'e':
                return ParseExpPart(pB,pE);
            case 'j':
            case 'J':
                pB++;
                return true;
            default:
                return false;
            }            
        }
        return false;
    }

    static bool Parse(tIt &pB,const tIt &pE)
    {
        tIt lSave=pB;
        
        bool lResult;
        switch(*pB)
        {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            lResult=ParseIntPart(pB,pE);
            break;
        case '.':
            lResult=ParsePointPart(pB,pE,false);
            break;
        default:
            return false;
            break;
        }
        
        if(!lResult)
        {
            pB=lSave;
            return false;
        }
        
        return true;
    }
};

/*namespace parser*/ } /*namespace bush*/ } /*namespace buola*/ }

#endif
